package org.manon.json.analyse;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.manon.json.meta.HasUniqueId;

/**
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 */
public final class Tree<T extends HasUniqueId<E>,E extends Comparable<E>> {
	
	private final Comparator<HasUniqueId<E>> _comparator;
	
	private final SortedSet<TreeNode<T,E>> _roots;
	
	public Tree(Comparator<HasUniqueId<E>> comparator) {
		_comparator = comparator;
		 _roots = new TreeSet<TreeNode<T,E>>(comparator);
	}

	@SuppressWarnings("all")
	public TreeNode<T,E> newTreeNode(T object) {
		return new TreeNode(object,this);
	}
	
	public void addRoot(TreeNode<T,E> node) {		
		_roots.add(node);
	}
	
	Comparator<HasUniqueId<E>> getComparator() {
		return _comparator;
	}
	
	public boolean contains(E[] path) {
		final Iterator<TreeNode<T,E>> iterator = _roots.iterator();
		TreeNode<T,E> item;
		
		while (iterator.hasNext()) {
			item = iterator.next();
			
			if (path[0].equals(item.getObject().getId())) {
				return item.contains(path,1);
			}
			
		}
		return false;
	}
	
	public TreeNode<T,E> search(String[] path) {
		
		if (path == null || path.length == 0) {
			return null;
		}
		
		final Iterator<TreeNode<T,E>> iterator = _roots.iterator();
		TreeNode<T,E> item;
		
		while (iterator.hasNext()) {
			item = iterator.next();
			
			if (path[0].equals(item.getObject().getId())) {
				return item.search(path,1);
			}
			
		}
		return null;
	}
	
	public String dump() {
		StringBuilder builder = new StringBuilder();
		builder.append("Tree Pretty Print : ");
		for (TreeNode<T,E> node : _roots) {
			builder.append("\n").append(node.printTree(6));
		}
		return builder.toString();
	}
	
	public Collection<T> values() {
		final List<T> values = new ArrayList<T>();
		final Iterator<TreeNode<T,E>> iterator = _roots.iterator();
		TreeNode<T,E> item;
		while (iterator.hasNext()) {
			item = iterator.next();
			values.add(item.getObject());
			item.values(values);
		}
		return values;
	}

	public Iterator<TreeNode<T, E>> iterator() {
		return _roots.iterator();
	}

}